package framework.server;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import common.Configuration;
import common.LogCategory;

/**
 * The command prompt startup of the framework
 *
 * @author	Orlin Tomov
 * @version	0.2
 *
 */
public class Startup {

	private static final Logger log = LogCategory.getCategory(Startup.class);

	/** The framework server instance */
	private Server server;

	/**
	 * Executes the server framework
	 *
	 * @param	args	the command line arguments
	 */
	public Startup(String[] args) throws Exception {
		/** hello world */
		System.out.println(Server.version);

		/** help message */
		if (isArg("-help", args)) {
			System.out.println(
				"Startup Flags:\n"+
				"\t-help\t\t\tThis Message\n"+
				"\t-admin\t\t\tThe admin port\n"+
				"\t-config [file],..[file]\t\tRead config from file\n");
			return;
		}

		/** determine config */
		List<File> cfg = determineConfig(args);

		/** instantiate server */
		server = Server.getServer(cfg);

		/** determine config */
		int registryPort = determineRegistryPort(args);

		/** connects admin */
		server.init(registryPort);

		Thread t = Thread.currentThread ();
		t.setName(Server.version);

		/** start server */
		try {
			server.run();
		} catch(Exception exception) {
			/**/log.error("Can't set up server", exception);
		}
	}

	/**
	 * determine the online config admin registry port
	 *
	 * @return	the online config admin registry port. if haven't returns default value.
	 */
	static int determineRegistryPort(String[] args) throws Exception {
		String p = getArg("-admin", args);
		if (p == null) {
			return Server.REGISTRY_PORT;
		}
		try {
			return Integer.parseInt(p);
		} catch (Exception e) {
		}
		return Server.REGISTRY_PORT;
	}

	/**
	 * determine the config files
	 *
	 * @return	the config files ArrayList that contains File elements which determine the config files
	 */
	private List<File> determineConfig(String[] args) throws Exception {
		String s = getArg("-config", args);
		if (s == null) {
			s = "services.xml";
		}
		List<File> configFiles = new ArrayList<File>();
		String configFile;
		while (s.indexOf(";") >= 0) {
			configFile = (String) s.substring(0, s.indexOf(";"));
			File file = new File(configFile);
			/** if could not find the config downloads default from the jar */
			if (!file.exists()) {
				file = loadConfig(configFile);
			}
			configFiles.add(file);
			s = s.substring(s.indexOf(";")+1);
		}
		configFile = s;
		File file = new File(configFile);
		/** if could not find the config downloads default from the jar */
		if (!file.exists()) {
			file = loadConfig(configFile);
		}
		configFiles.add(file); 
		log.info("Loading configuration from: ");
		for (File f: configFiles) {
			log.info(f.getCanonicalPath());
		}
		return configFiles;
	}

	/**
	 * Download default config file from a jar.
	 * 
	 * @param	configFile	string value that represents the path and the name of the config file
	 * @return the config file
	 */
	private File loadConfig(String configFile) {
		try {
			InputStream inputstream = getClass().getResourceAsStream(configFile);
			FileOutputStream fileoutputstream = new FileOutputStream(Configuration.formDefaultConfigurationPath(configFile), true);
			byte abyte0[] = new byte[1024];
			int i = 0;
			do {
				fileoutputstream.write(abyte0, 0, i);
				i = inputstream.read(abyte0, 0, 1024);
			} while(i > -1);
			inputstream.close();
			fileoutputstream.close();
		} catch (Exception exception) {
			log.warn("massive internal error " + exception);
		}
		return new File(Configuration.formDefaultConfigurationPath(configFile));
	}

	private boolean isArg(String s, String[] args) {
		for (int i = 0; i < args.length; i++) {
			String s1 = args[i];
			if (s1.equals(s)) {
				return true;
			}
		}
		return false;
	}

	private static String getArg(String s, String[] args) {
		for (int i = 0; i < args.length; i++) {
			String s1 = args[i];
			if (s1.equals(s)) {
				try {
					args[i] = "";
					String s2 = "";
					for (int j = i + 1; j < args.length; j++) {
						String s3 = args[j];
						if (s3.isEmpty() || s3.startsWith("-")) {
							break;
						}
						if (s2.isEmpty()) {
							s2 = s3;
						} else {
							s2 += ";" + s3;
						}
						args[j] = "";
					}
					return s2;
				} catch(ArrayIndexOutOfBoundsException exception) {
					return null;
				}
			}
		}
		return null;
	}

	/**
	 * Constructs the startup of the server framework
	 * 
	 * -config ../etc/services.xml
	 * -Dappserver.home=/workspace/appserver
	 *
	 * @param	args	the command line arguments
	 */
	public static void main(String[] args) {
		try {
			new Startup(args);
		} catch(Exception exception) {
			log.fatal(exception.getMessage());
		}
	}
}
